package com.stupidzhe.jdklearning.map;

import java.util.*;

/**
 * Created by Mr.W on 2017/9/27.
 */
public class SimpleHashMapImpl<K, V> implements SimpleHashMap<K, V> {

    private static final int LIST_SIZE = 5;
    @SuppressWarnings("unchecked")
    private LinkedList<MapEntry<K, V>>[] buckets = new LinkedList[LIST_SIZE];

    private class MapEntry<K, V> {

        private final K key;
        private V value;

        //构造函数
        public MapEntry(K k, V v) {
            key = k;
            value = v;
        }

        final K getKey() {
            return key;
        }

        final V getValue() {
            return value;
        }

        final V setValue(V v) {
            V tmpVal = value;
            value = v;
            return tmpVal;
        }

        @Override
        public boolean equals(Object o) {
            return this.hashCode() == o.hashCode();
        }

        @Override
        public int hashCode() {
            return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
        }
    }

    @Override
    public V put(K key, V val) {
        if (null == key) {
            return null;
        }
        int index;
        V oldVal = null;
        index = Math.abs(key.hashCode()) % LIST_SIZE;
        if (buckets[index] == null) {
            buckets[index] = new LinkedList<>();
        }
        LinkedList<MapEntry<K, V>> bucket = buckets[index];

        boolean found = false;
        for (MapEntry<K, V> tmpVal : bucket) {
            if (tmpVal.getKey().equals(key)) {
                oldVal = tmpVal.getValue();
                tmpVal.setValue(val);
                found = true;
                break;
            }
        }
        if (!found) {
            bucket.add(new MapEntry<>(key, val));
        }
        return oldVal;
    }

    @Override
    public V get(Object key) {
        int index;
        index = Math.abs(key.hashCode()) % LIST_SIZE;
        LinkedList<MapEntry<K, V>> bucket = buckets[index];
        if (bucket == null) {
            return null;
        }
        for (MapEntry<K, V> tmpVal : bucket) {
            if (tmpVal.getKey().equals(key)) {
                return tmpVal.getValue();
            }
        }
        return null;
    }

    @Override
    public V remove(K key) {
        int index;
        index = Math.abs(key.hashCode()) % LIST_SIZE;
        LinkedList<MapEntry<K, V>> bucket = buckets[index];
        if (bucket == null) {
            return null;
        }

        for (MapEntry<K, V> tmpVal : bucket) {
            if (tmpVal.getKey().equals(key)) {
                bucket.remove(tmpVal);
                return tmpVal.getValue();
            }
        }
        return null;
    }
}

